package com.guli.mall.wms.config;

import com.guli.common.constant.MessageQueueConstant;
import com.guli.common.constant.OrderConstant;
import com.guli.common.constant.WareConstant;
import com.guli.mall.wms.service.WareSkuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.HashMap;

/*
 * @Author 罗俊
 * @date 2020/11/25 - 4:42 下午
 *
 */
@Configuration
@Slf4j
public class RabbitMqConfig implements InitializingBean {

    @Resource
    AmqpAdmin amqpAdmin;

    @Resource
    RabbitTemplate rabbitTemplate;

    @Override
    public void afterPropertiesSet() throws Exception {

        createExchangeQueueAndBinding();

        /**
         * 配置 RabbitTemplate 的发送确认
         * */
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                log.info("定时解锁库存操作，订单号：{}，已发送到MQ", correlationData.getId());
            }
        });

        rabbitTemplate.setReturnCallback((Message message, int replyCode, String replyText, String exchange, String routingKey) -> {
            //TODO 解锁库存消息发送失败的处理逻辑
            log.error("库存服务：错误代码：{}：{}，原本应该发送到{}交换机，路由key：{}，错误消息：{}；", replyCode, replyText, exchange, routingKey,message);

        });

    }


    public void createExchangeQueueAndBinding() {

        TopicExchange topicExchange = new TopicExchange(WareConstant.STOCK_EVENT_EXCHANGE, true, false);

        amqpAdmin.declareExchange(topicExchange);

        amqpAdmin.declareQueue(getDelayQueue());

        Queue queue = new Queue(WareConstant.STOCK_RELEASE_QUEUE, true, false, false);

        amqpAdmin.declareQueue(queue);

        Binding lockStockBinding = new Binding(WareConstant.STOCK_DELAY_QUEUE, Binding.DestinationType.QUEUE, WareConstant.STOCK_EVENT_EXCHANGE, WareConstant.STOCK_LOCKED_DELAY_ROUTING_KEY, null);

        amqpAdmin.declareBinding(lockStockBinding);

        /**
         * 注意 这个路由key 的后缀是 # ，表示匹配所有
         * */
        Binding releaseStockBinding = new Binding(WareConstant.STOCK_RELEASE_QUEUE, Binding.DestinationType.QUEUE, WareConstant.STOCK_EVENT_EXCHANGE, WareConstant.STOCK_RELEASE_ROUTING_KEY, null);

        amqpAdmin.declareBinding(releaseStockBinding);

        log.info("库存交换机、队列、绑定完成");

        /**
         * 额外创建一个队列，用于将锁库存的信息写入到数据库
         * */
        /*Queue recordLockStockQueue = new Queue(WareConstant.STOCK_RECORD_QUEUE, true, false, false);

        amqpAdmin.declareQueue(recordLockStockQueue);

        Binding recordLockStockBinding = new Binding(WareConstant.STOCK_RECORD_QUEUE, Binding.DestinationType.QUEUE, WareConstant.STOCK_EVENT_EXCHANGE, WareConstant.STOCK_LOCKED_ROUTING_KEY, null);

        amqpAdmin.declareBinding(recordLockStockBinding);*/

        Queue stockDeductQueue = new Queue(WareConstant.STOCK_DEDUCTION_QUEUE, true, false, false, null);

        Binding deductStockRoutingKey = new Binding(WareConstant.STOCK_DEDUCTION_QUEUE, Binding.DestinationType.QUEUE, WareConstant.STOCK_EVENT_EXCHANGE, WareConstant.STOCK_DEDUCTION_ROUTING_KEY, null);

        amqpAdmin.declareQueue(stockDeductQueue);

        amqpAdmin.declareBinding(deductStockRoutingKey);


    }

    /**
     * 获取延迟队列
     *
     * @return
     */
    private Queue getDelayQueue() {
        HashMap<String, Object> arguments = new HashMap<>();

        arguments.put(MessageQueueConstant.X_DEAD_LETTER_EXCHANGE, WareConstant.STOCK_EVENT_EXCHANGE);

        arguments.put(MessageQueueConstant.X_DEAD_LETTER_ROUTING_KEY, WareConstant.STOCK_RELEASE_ROUTING_KEY);

        arguments.put(MessageQueueConstant.X_MESSAGE_TTL, OrderConstant.ORDER_PAYMENT_TIME); //30分钟后仍然未支付，就解锁库存

        return new Queue(WareConstant.STOCK_DELAY_QUEUE, true, false, false, arguments);
    }

}
